From 6020fcb84859f63343a74f46bf2f2d3d8e5a195c Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 18 Nov 2010 12:26:27 +0000 Subject: [PATCH] rcu_lock(current->domain) does not need to disable preemption. If the guest sleeps in hypervisor context, it should not be destroyed until execution reaches a safe point (i.e., guest context). This is not implemented yet. :-) But the next patch will rely on it, to allow an HVM guest to execute hypercalls that indirectly invoke __hvm_copy() within an rcu_lock_current_domain() region. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 2 +- xen/arch/x86/physdev.c | 12 ++++-------- xen/common/domain.c | 9 ++++++--- xen/include/xen/sched.h | 8 +++++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 3cda1afffd..ec4ac8cbeb 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2759,7 +2759,7 @@ static struct domain *get_pg_owner(domid_t domid) if ( likely(domid == DOMID_SELF) ) { - pg_owner = rcu_lock_domain(curr); + pg_owner = rcu_lock_current_domain(); goto out; } diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 6a12f0013e..7f8e71a28b 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -37,10 +37,8 @@ static int physdev_map_pirq(struct physdev_map_pirq *map) if ( !map ) return -EINVAL; - if ( map->domid == DOMID_SELF ) - d = rcu_lock_domain(current->domain); - else - d = rcu_lock_domain_by_id(map->domid); + d = (map->domid == DOMID_SELF) ? rcu_lock_current_domain() + : rcu_lock_domain_by_id(map->domid); if ( d == NULL ) return -ESRCH; @@ -165,10 +163,8 @@ static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap) struct domain *d; int ret; - if ( unmap->domid == DOMID_SELF ) - d = rcu_lock_domain(current->domain); - else - d = rcu_lock_domain_by_id(unmap->domid); + d = (unmap->domid == DOMID_SELF) ? rcu_lock_current_domain() + : rcu_lock_domain_by_id(unmap->domid); if ( d == NULL ) return -ESRCH; diff --git a/xen/common/domain.c b/xen/common/domain.c index 1a08636756..803c640a7f 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -398,7 +398,7 @@ struct domain *get_domain_by_id(domid_t dom) struct domain *rcu_lock_domain_by_id(domid_t dom) { - struct domain *d; + struct domain *d = NULL; rcu_read_lock(&domlist_read_lock); @@ -407,12 +407,15 @@ struct domain *rcu_lock_domain_by_id(domid_t dom) d = rcu_dereference(d->next_in_hashbucket) ) { if ( d->domain_id == dom ) - return d; + { + rcu_lock_domain(d); + break; + } } rcu_read_unlock(&domlist_read_lock); - return NULL; + return d; } int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index e817e3128b..2ac43fc4b2 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -439,18 +439,20 @@ int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d); /* Finish a RCU critical region started by rcu_lock_domain_by_id(). */ static inline void rcu_unlock_domain(struct domain *d) { - rcu_read_unlock(&domlist_read_lock); + if ( d != current->domain ) + rcu_read_unlock(&domlist_read_lock); } static inline struct domain *rcu_lock_domain(struct domain *d) { - rcu_read_lock(d); + if ( d != current->domain ) + rcu_read_lock(d); return d; } static inline struct domain *rcu_lock_current_domain(void) { - return rcu_lock_domain(current->domain); + return /*rcu_lock_domain*/(current->domain); } struct domain *get_domain_by_id(domid_t dom); -- 2.30.2